package com.satan.upload.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.satan.upload.entity.File;
import com.satan.upload.mapper.FileMapper;
import com.satan.upload.service.ChunkService;
import com.satan.upload.service.FileService;
import com.satan.upload.vo.ResultVo;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author Demon
 * @description 针对表【tb_file】的数据库操作Service实现
 * @createDate 2023-09-13 14:28:42
 */
@Service
@Slf4j
public class FileServiceImpl extends ServiceImpl<FileMapper, File>
        implements FileService {
    @Autowired
    private ChunkService chunkService;

    @Value("${file.path}")
    private String filePath;

    @Override
    public Boolean addFile(File file) {
        //insert into file(f_name,f_md5,f_size) values(#{name},#{md5},#{size})
        boolean saved = save(file);

        return saved;
    }

    @Override
    public Boolean selectFileByMd5(String md5) {
        LambdaQueryWrapper<File> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(File::getFMd5, md5);
        File file = getOne(lambdaQueryWrapper);
        return !ObjectUtil.isEmpty(file);
    }

    @Override
    public List<File> selectFileList() {
        return null;
    }

    //校验文件是否存在
    @Override
    public ResultVo checkFile(String md5) {
        log.info("检查MD5:" + md5);
        //首先检查是否有完整的文件
        Boolean isUploaded = selectFileByMd5(md5);
        Map<String, Object> map = new HashMap<>();
        map.put("isUploaded",isUploaded);
        //如果有，就返回秒传
        if(isUploaded){
            return ResultVo.success(map);
        }
        //如果没有，就查找分片信息，并返回给前端
        List<Integer> chunkList = chunkService.selectChunkListByMd5(md5);
        map.put("chunkList",chunkList);
        return ResultVo.success(map);
    }

    @Override
    public ResultVo uploadChunk(MultipartFile chunk, String md5, Integer index, Integer chunkTotal, Long fileSize, String fileName, Long chunkSize) {

        String[] splits = fileName.split("\\.");
        String type = splits[splits.length-1];
        String resultFileName = filePath+md5+"."+type;

        chunkService.saveChunk(chunk,md5,index,chunkSize,resultFileName);
        log.info("上传分片："+index +" ,"+chunkTotal+","+fileName+","+resultFileName);
        if(Objects.equals(index, chunkTotal)){
            File file = File.builder().fName(fileName).fMd5(md5).fSize(fileSize).build();
            //文件信息保存数据库
            addFile(file);
            chunkService.deleteChunkByMd5(md5);
            return ResultVo.success("文件上传成功",index);

        }else{
            return ResultVo.success("分片上传成功",index);
        }
    }

    @Override
    public ResultVo getFileList() {
        log.info("查询文件列表");
//        select * from tb_file order by f_id desc
        LambdaQueryWrapper<File> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.orderByDesc(File::getFId);
        List<File> fileList = list(lambdaQueryWrapper);
        return ResultVo.success(fileList);
    }

    @Override
    public void download(String md5, String fileName, Integer chunkSize, Integer chunkTotal, Integer index, HttpServletResponse response) {
        String[] splits = fileName.split("\\.");
        String type = splits[splits.length - 1];
        String resultFileName = filePath + md5 + "." + type;

        java.io.File resultFile = new java.io.File(resultFileName);

        long offset = (long) chunkSize * (index - 1);
        if(Objects.equals(index, chunkTotal)){
            offset = resultFile.length() -chunkSize;
        }
        byte[] chunk = chunkService.getChunk(index, chunkSize, resultFileName,offset);


        log.info("下载文件分片" + resultFileName + "," + index + "," + chunkSize + "," + chunk.length+","+offset);
//        response.addHeader("Access-Control-Allow-Origin","Content-Disposition");
        response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
        response.addHeader("Content-Length", "" + (chunk.length));
        response.setHeader("filename", fileName);


        response.setContentType("application/octet-stream");
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            out.write(chunk);
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}




